"use client";
import { useEffect, useState } from "react";
import { abi, contractAddresses } from "../constants"
import { useWeb3Contract, useMoralis } from "react-moralis"
import { ethers } from "ethers"

// have a function to enter the lottory contract

export default function LotteryEntrance() {
    const { chainId: chainIdHex, isWeb3Enabled, Moralis } = useMoralis()
    const chainIdString = chainIdHex ? parseInt(chainIdHex).toString() : "31337"
    console.log(`chainIdString is ${chainIdString}`)

    const contractAddress = contractAddresses[chainIdString]
        ? contractAddresses[chainIdString][0]
        : null
    console.log(`Contract Address is ${contractAddress}`)

    // state hooks
    // https://stackoverflow.com/questions/58252454/react-hooks-using-usestate-vs-just-variables
    // 在组件重新渲染时保留值，如果只是一个普通变量, 每次重新渲染时都会被重置
    const [ entranceFee, setEntranceFee ] = useState("0")
    const [ numberOfPlayers, setNumberOfPlayers ] = useState("0")
    const [ players, setPlayers] = useState([]) // array of addresses
    const [ recentWinner, setRecentWinner ] = useState("0")

    /* view functions
        getEntranceFee
        getNumberOfPlayers
        getRecentWinner
    */
    const { runContractFunction: getEntranceFee } = useWeb3Contract({
        abi: abi,
        contractAddress: contractAddress,
        functionName: "getEntranceFee",
        params: {},
    })
    // Another way we could make a contract call:
    // const options = { abi, contractAddress: raffleAddress }
    // const fee = await Moralis.executeFunction({
    //     functionName: "getEntranceFee",
    //     ...options,
    // })

    const { runContractFunction: getPlayersNumber } = useWeb3Contract({
        abi: abi,
        contractAddress: contractAddress,
        functionName: "getNumberOfPlayers",
        params: {},
    })

    const { runContractFunction: getRecentWinner } = useWeb3Contract({
        abi: abi,
        contractAddress: contractAddress,
        functionName: "getRecentWinner",
        params: {},
    })

    async function updateUIValues() {
        // try to read the raffle entrance fee
        const entranceFeeFromCall = (await getEntranceFee()).toString()
        const numPlayersFromCall = (await getPlayersNumber()).toString()
        const recentWinnerFromCall = await getRecentWinner()
        setEntranceFee(entranceFeeFromCall) // setState hook 是异步的,会触发组件重新渲染,但不会立即更新变量的值,而是在下一次渲染时更新
        setNumberOfPlayers(numPlayersFromCall) 
        setRecentWinner(recentWinnerFromCall)
        updatePlayers(Number(numPlayersFromCall))
    }

    useEffect(
        () => {
            console.log("useEffect triggered, isWeb3Enabled:", isWeb3Enabled)
            if (isWeb3Enabled) {
                updateUIValues()
            }
        } , [isWeb3Enabled]
    )

    const { 
        data: enterTxResponse, 
        // error, 
        runContractFunction: enterRaffle, // 将对象的属性重命名为 enterRaffle, 代替 runContractFunction,让代码更语义化
        isFetching, 
        isLoading 
    } =
    useWeb3Contract();

    const options = {
        abi: abi,
        contractAddress: contractAddress,
        functionName: "enterRaffle",
        params: {},
        msgValue: entranceFee,
    }

    const { runContractFunction: getPlayer } = useWeb3Contract()
    // async function getPlayerDynamic(index) {
    //     const player = await Moralis.executeFunction({
    //         abi,
    //         contractAddress,
    //         functionName: "getPlayer",
    //         params: { index }
    //     })
    //     return player
    // }

    async function updatePlayers(numberOfPlayersInt) {
        setPlayers([]) // 先清空当前玩家列表

        for (let i = 0; i < numberOfPlayersInt; i++) {
            // const playerFromCall = await getPlayerDynamic(i)
            const getPlayerOptions = {
                abi: abi,
                contractAddress: contractAddress,
                functionName: "getPlayer",
                params: { index: i }, 
            }
            const playerFromCall = await getPlayer({ params: getPlayerOptions })
            setPlayers((prevPlayers) => [...prevPlayers, playerFromCall])
            // 或者也可以用下面这种方式, 但不推荐, 因为这种方式依赖于 players 的当前值, 可能会有异步问题
            // setPlayers([...players, playerFromCall])
            // 也可以直接在这里打印出来
            // console.log(`Player ${i}: ${playerFromCall}`)
        }
    }

    function handleNewNotification(tx) { // 也可以写为 const handleNewNotification = (tx) => {
        console.log("Transaction Complete ...")
        if (tx) {
            console.log("Contract Address:", tx.to) // 合约地址
            console.log("Transaction Hash:", tx.hash) // 交易哈希
            console.log("From:", tx.from) // 交易发起地址
        }
    }

    const handleSuccess = async (tx) => { // 也可以写为 async function handleSuccess(tx) {
        try {
            await tx.wait(1)
            updateUIValues()
            handleNewNotification(tx)
        } catch (error) {
            console.log(error)
        }
    }

    return (
        <>
            <div className="border-b-2 border-black p-5">
                <h1 className="py-4 px-4 font-bold text-3xl">Hi from LotteryEntrance!</h1> 
                { contractAddress ? (
                    <>
                        <button
                            className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded ml-auto"
                            onClick={
                                async () => {
                                    await enterRaffle(
                                        { 
                                            params: options,
                                            onSuccess: handleSuccess,
                                            onError: (error) => console.log(error),
                                        }
                                    )
                                }
                            }
                            disabled={isLoading || isFetching}
                        >
                            { isLoading || isFetching ? (
                                <div className="animate-spin spinner-border h-8 w-8 border-b-2 rounded-full"></div>
                            ) : (   
                                "Enter Raffle" 
                            )}
                        </button>
                        <div>Raffle Contract Address: {contractAddress}</div>
                        <div>Entrance Fee: {ethers.utils.formatUnits(entranceFee, "ether")} ETH</div>
                        <div>The current number of players is: {numberOfPlayers}</div>
                        <div>Players: {players.length > 0 ? players.join(", ") : " No players yet"}</div>
                        <div>The most previous winner was: {recentWinner}</div>
                    </>):
                    (<div> Please connect to a supported chain </div>)
                }
            </div>
        </>
    )
}
